setState是同步还是异步 您所在的位置:网站首页 settimeout setstate setState是同步还是异步

setState是同步还是异步

#setState是同步还是异步| 来源: 网络整理| 查看: 265

在讨论这个问题之前,先看一个问题

setState执行后打印state是更新前的还是更新后的? 合成事件中 更新之前的值 class App extends React.Component { state = { count: 0 } handleClick = () => { this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之前的值 } render() { return ( 点击 ) } } 复制代码 钩子函数中 更新之前的值 class App extends React.Component { state = { count: 0 } componentDidMount() { this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之前的值 } render() { return null } } 复制代码 原生事件中 更新之后的值 class App extends React.Component { state = { count: 0 } handleClick = () => { this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之后的值 } componentDidMount() { document.body.addEventerListener("click", this.handleCLick) } render() { return ... } } 复制代码 setTimeout中 更新之后的值 class App extends React.Component { state = { count: 0 } handleClick = () => { setTimeout(() =>{ this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之后的值 }) } render() { return ( 点击 ) } } 复制代码 结论

从上面的例子可以看出

在合成事件和生命周期中是"异步"的 在原生事件和setTimeout中是同步的

但是,这里说的异步真的是异步吗?那么就用setState和异步事件做比较,看下打印顺序

setState和异步做比较 包含在setTimeout中和异步做比较 handleClick = () => { setTimeout(() => { console.log('宏任务触发') }) Promise.resolve().then(() => { console.log('微任务触发') }) setTimeout(() => { this.setState({ count: this.state.count + 1 }, () => { console.log('setState变化') }) }) } 复制代码

打印顺序: 微任务触发 -> 宏任务触发 -> setState变化

setState直接和异步做比较 handleClick = () => { setTimeout(() => { console.log('宏任务触发') }) Promise.resolve().then(() => { console.log('微任务触发') }) this.setState({ count: this.state.count + 1 }, () => { console.log('setState变化') }) } 复制代码

打印顺序:setState变化 -> 微任务触发 -> 宏任务触发

由此可见:setState不是一个异步的任务,只是一个被延迟执行的同步函数

总结

setState是一个伪异步,或者可以称为defer,即延迟执行但本身还在一个事件循环,所以它的执行顺序在同步代码后、异步代码前。为什么会有这种现象?这就要说到react的合成事件了,react的批处理更新也得益于合成事件



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有